let _scriptLoaded_: ObjectValue = {}
let _urlCallback_: ObjectValue = {}
function execCallback(url: string, args: any) {
  let cbs = _urlCallback_[url]
  while (cbs.length > 0) {
    let cb = cbs.shift()
    if (cb) {
      cb.apply(null, args)
    }
  }
}

function ensureProtocol(url: string) {
  return url.replace(/^http(s)?:/, location.protocol)
}

function load(url: string, callback: Function) {
  url = ensureProtocol(url)

  if (!_urlCallback_[url]) {
    _urlCallback_[url] = []
  }
  _urlCallback_[url].push(callback)

  if (_scriptLoaded_[url] === 200) {
    execCallback(url, [null, 'cached'])
    return
  }
  if (_scriptLoaded_[url] === 400) {
    execCallback(url, ['error'])
    return
  }
  if (_scriptLoaded_[url] === 500) {
    execCallback(url, ['timeout'])
    return
  }

  if (_scriptLoaded_[url] === 100) {
    return
  }

  _scriptLoaded_[url] = 100

  let timeOut = false
  let timer: any = 0
  let script: any = creatScript(url)
  let retryNode = creatScript(url + '?' + new Date().getTime())

  // 首次加载js成功
  script.onload = function () {
    if (!this.readyState || /^(loaded|complete)$/.test(this.readyState)) {
      if (!timeOut) {
        clearTimeout(timer)
        execCallback(url, [null, 'ok'])
      }
      _scriptLoaded_[url] = 200
      script.onload = script.onreadystatechange = null
    }
  }
  // 首次加载错误
  script.onerror = function () {
    if (!timeOut) {
      clearTimeout(timer)
      let el = document.getElementById(script.id)
      if (el) {
        document.getElementsByTagName('head')[0].removeChild(el)
      }
      document.getElementsByTagName('head')[0].appendChild(retryNode)
      timeOutAgain()
    }
    script.onerror = null
  }
  // 第二次加载js成功
  retryNode.onload = function () {
    if (!(this as any).readyState || /^(loaded|complete)$/.test((this as any).readyState)) {
      if (!timeOut) {
        clearTimeout(timer)
        execCallback(url, [null, 'ok'])
      }
      _scriptLoaded_[url] = 200
      retryNode.onload = script.onreadystatechange = null
    }
  }
  // 第二次报错
  retryNode.onerror = function () {
    if (!timeOut) {
      clearTimeout(timer)
      _scriptLoaded_[url] = 400
      execCallback(url, ['error'])
    }
    retryNode.onerror = null
  }

  // 首次超时
  timer = setTimeout(() => {
    timeOut = true
    let el = document.getElementById(script.id)
    if (el) {
      document.getElementsByTagName('head')[0].removeChild(el)
    }
    document.getElementsByTagName('head')[0].appendChild(retryNode)
    script.onload = script.onreadystatechange = null
    timeOutAgain()
  }, 10 * 1000)

  // 二次超时
  let timeOutAgain = function () {
    timeOut = false
    timer = setTimeout(() => {
      timeOut = true
      execCallback(url, [Error('timeout')])
    }, 10 * 1000)
  }

  document.getElementsByTagName('head')[0].appendChild(script)
  return 0
}

function creatScript(url: string) {
  let script = document.createElement('script')
  script.setAttribute('type', 'text/javascript')
  script.src = url
  script.id = url.split('/').slice(-3, -1).join('')
  return script
}

let loadScript = function (url: string) {
  return new Promise((resolve) => {
    load(url, (err: any, status: any) => {
      resolve({
        err: err,
        status: status,
      })
    })
  })
}

export default loadScript
